home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
TeX 1995 July
/
TeX CD-ROM July 1995 (Disc 1)(Walnut Creek)(1995).ISO
/
dviware
/
dvi2ps
/
psdvi
/
psdvi.c
< prev
next >
Wrap
C/C++ Source or Header
|
1990-10-01
|
14KB
|
585 lines
#ifndef LINT
static char *rcs_header =
"$Header: psdvi.c,v 1.5 87/11/27 16:39:25 elwell Exp $";
#endif
/*
* psdvi -- convert TeX DVI files to PostScript
*
* Written by Clayton M. Elwell, The Ohio State University
*
* Edit History:
*
* $Log: psdvi.c,v $
* Revision 1.5 87/11/27 16:39:25 elwell
* Split out PostScript prologue into separate file
*
* Revision 1.4 87/09/17 22:13:53 elwell
* Cleaned up PostScript prologue
*
* Revision 1.3 87/07/30 12:21:43 elwell
* Fixed bug in font scaling (TeX points vs. PostScript points)
*
* Revision 1.2 87/07/29 11:23:02 elwell
* Added support for oblique (slanted) fonts. The PostScript
* macro that implements this was written by L.A. Carr (as far
* as I can tell).
*
* Revision 1.1 87/07/14 19:11:07 elwell
* Initial revision
*
*
*/
#include <stdio.h>
char *malloc();
#ifdef BSD
#include <pwd.h>
#include <strings.h>
#endif
char profile[80] = "/usr/local/lib/ps/psdvi.pro";
#define SETC_000 0
#define SETC_127 127
#define SET1 128
#define SET2 129
#define SET3 130
#define SET4 131
#define SET_RULE 132
#define PUT1 133
#define PUT2 134
#define PUT3 135
#define PUT4 136
#define PUT_RULE 137
#define NOP 138
#define BOP 139
#define EOP 140
#define PUSH 141
#define POP 142
#define RIGHT1 143
#define RIGHT2 144
#define RIGHT3 145
#define RIGHT4 146
#define W0 147
#define W1 148
#define W2 149
#define W3 150
#define W4 151
#define X0 152
#define X1 153
#define X2 154
#define X3 155
#define X4 156
#define DOWN1 157
#define DOWN2 158
#define DOWN3 159
#define DOWN4 160
#define Y0 161
#define Y1 162
#define Y2 163
#define Y3 164
#define Y4 165
#define Z0 166
#define Z1 167
#define Z2 168
#define Z3 169
#define Z4 170
#define FONT_00 171
#define FONT_63 234
#define FNT1 235
#define FNT2 236
#define FNT3 237
#define FNT4 238
#define XXX1 239
#define XXX2 240
#define XXX3 241
#define XXX4 242
#define FNT_DEF1 243
#define FNT_DEF2 244
#define FNT_DEF3 245
#define FNT_DEF4 246
#define PRE 247
#define POST 248
#define POST_POST 249
char *program_name;
FILE *dvi_file;
open_dvi_file(s)
char *s;
{
dvi_file = fopen(s, "r");
if (!dvi_file) error("Unable to open DVI file %s", s);
}
#define set_dvi_file_pos(i) fseek(dvi_file, (long) (i), 0)
#define get_dvi_file_pos() ftell(dvi_file)
get_byte() /* get a byte from the DVI file, unsigned */
{
register int i;
if ((i = getc(dvi_file)) == EOF)
error("unexpected end of file on DVI file");
return i & 255;
}
signed_byte()
{
register int i;
i = get_byte();
if (i > 127) i -= 256;
return i;
}
get_two_bytes()
{
register int c1, c2;
c1 = get_byte(); c2 = get_byte();
return c1 * 256 + c2;
}
signed_pair()
{
register int c1, c2;
c1 = signed_byte(); c2 = get_byte();
return c1 * 256 + c2;
}
get_three_bytes()
{
register int c1, c2 ,c3;
c1 = get_byte(); c2 = get_byte(); c3 = get_byte();
return (c1 * 256 + c2) * 256 + c3;
}
get_signed_trio()
{
register int c1, c2, c3;
c1 = signed_byte(); c2 = get_byte(); c3 = get_byte();
return (c1 * 256 + c2) * 256 + c3;
}
signed_quad()
{
int i;
register int c1, c2, c3, c4;
c1 = signed_byte(); c2 = get_byte(); c3 = get_byte(); c4 = get_byte();
i = ((c1*256+c2)*256+c3)*256+c4;
return i;
}
get_dvi_str(l, s)
int l;
char *s;
{
int i;
for (i = 0; i < l; i++) s[i] = get_byte();
s[i] = 0;
}
include_file(s)
char *s;
{
FILE *fp;
int c;
if (!(fp = fopen(s, "r"))) return -1;
while ((c = getc(fp)) != EOF) putchar(c);
fclose(fp);
return 0;
}
double mag;
write_preamble_comment()
{
register int byte1, byte2;
#ifdef BSD
struct passwd *pw;
char h[80];
#endif
byte1 = get_byte(); byte2 = get_byte();
if (byte1 != PRE || byte2 != 2) error ("input file is not a DVI file");
set_dvi_file_pos(14);
printf("%%%%Creator: ");
byte1 = get_byte();
while (byte1--) putchar(get_byte());
putchar('\n');
#ifdef BSD
pw = getpwuid(getuid());
gethostname(h, 80);
if (index(pw->pw_gecos, ','))
*(index(pw->pw_gecos, ',')) = 0;
printf("%%%%For: %s@%s (%s)\n", pw->pw_name, h, pw->pw_gecos);
#endif
}
scmp(s1, s2)
char **s1;
char **s2;
{
return strcmp(*s1, *s2);
}
int last_bop_pointer;
double conv, true_conv, mag;
load_postamble_and_fonts()
{
int pos, op, dvi_mag, numerator, denominator, max_v, max_h, max_s,
total_pages, p;
int scaled, design;
int waste, length;
char str[200];
char *ftab[500];
int nfonts, i;
/* find postamble */
fseek(dvi_file, -5L, 2); /* find end of file - 5 */
pos = get_dvi_file_pos();
for (op = get_byte(); op == 223;) {
pos--; set_dvi_file_pos(pos); op = get_byte();
}
set_dvi_file_pos(pos - 4);
pos = signed_quad();
/* load postamble proper */
set_dvi_file_pos(pos + 1); /* just past the POST command */
last_bop_pointer = signed_quad();
numerator = signed_quad();
denominator = signed_quad();
dvi_mag = signed_quad();
mag = ((double) dvi_mag) / 1000.0;
conv = (((double) numerator)/254000.0)*(72.0/((double) denominator));
true_conv = conv;
conv = true_conv * mag;
max_v = signed_quad();
max_h = signed_quad();
max_s = get_two_bytes();
total_pages = get_two_bytes();
pos = get_dvi_file_pos();
printf("%%%%DocumentFonts:");
nfonts = 0;
for (op = get_byte(); op != POST_POST; op = get_byte()) {
if (op >= FNT_DEF1 && op <= FNT_DEF4) {
p = first_par(op);
signed_quad();
scaled = signed_quad();
design = signed_quad();
waste = get_byte(); length = get_byte() + waste;
get_dvi_str(length, str);
for (i = 0; i < nfonts; i++)
if (!strcmp(str, ftab[i])) break;
if (i == nfonts) {
ftab[i] = malloc(strlen(str)+1);
strcpy(ftab[i], str);
nfonts++;
}
}
}
qsort(ftab, nfonts, sizeof(char *), scmp);
puts(ftab[0]);
for (i = 1; i < nfonts; i++) {
printf("%%%%+%s\n", ftab[i]);
free(ftab[i]);
}
set_dvi_file_pos(pos);
printf("%%%%Pages: %d\n%%%%EndComments\n", total_pages);
include_file(profile);
for (op = get_byte(); op != POST_POST; op = get_byte()) {
if (op >= FNT_DEF1 && op <= FNT_DEF4) {
p = first_par(op);
signed_quad();
scaled = signed_quad();
design = signed_quad();
waste = get_byte(); length = get_byte() + waste;
get_dvi_str(length, str);
/* notice correction factor between TeX and PostScript points */
printf("/f%d { %g /%s tf } def\n", p,
(((double)scaled)/((double)design))*mag*0.996264010, str);
}
}
puts("%%EndProlog");
}
first_par(o)
int o;
{
if (o >= SETC_000 && o <= SETC_127) return (o - SETC_000);
if (o >= FONT_00 && o <= FONT_63) return (o - FONT_00);
switch (o) {
case SET1: case PUT1: case FNT1: case XXX1: case FNT_DEF1:
return get_byte();
case SET2: case PUT2: case FNT2: case XXX2: case FNT_DEF2:
return get_two_bytes();
case SET3: case PUT3: case FNT3: case XXX3: case FNT_DEF3:
return get_three_bytes();
case RIGHT1: case W1: case X1: case DOWN1: case Y1: case Z1:
return signed_byte();
case RIGHT2: case W2: case X2: case DOWN2: case Y2: case Z2:
return signed_pair();
case RIGHT3: case W3: case X3: case DOWN3: case Y3: case Z3:
return get_signed_trio();
case SET4: case SET_RULE: case PUT4: case PUT_RULE: case RIGHT4:
case W4: case X4: case DOWN4: case Y4: case Z4: case FNT4:
case XXX4: case FNT_DEF4:
return signed_quad();
case W0:
return 0;
case X0:
return 0;
case Y0:
return 0;
case Z0:
return 0;
case NOP: case BOP: case EOP: case PUSH: case POP: case PRE:
case POST: case POST_POST:
default:
return 0;
}
}
char cur_name[200];
int first_bop_pointer;
find_starting_page()
{
int p, found, counts_match, i;
found = 0;
for (p = last_bop_pointer; p >= 0; p = signed_quad()) {
set_dvi_file_pos(p + 1); /* move to byte after BOP */
/* match counts against starting page spec -- ignore for now */
for (i = 0; i < 10; i++)
signed_quad();
first_bop_pointer = p;
found = 1;
}
if (!found) error ("Starting page number could not be found");
}
int cur_font;
process_pages()
{
char waste_string[200]; /* string shaped waste basket */
int waste; /* integer shaped waste basket */
int beginning_of_page, pages_processed, fonts_on_page, op, p;
int k, f, width, pxl_height, pxl_width;
int length;
int scaled_size, design_size;
set_dvi_file_pos(first_bop_pointer);
pages_processed = 0;
for (op = get_byte(); op != POST; op = get_byte()) {
switch (op) {
case BOP:
printf("%%%%Page: %d %d\nbop ", signed_quad(),
pages_processed+1);
/* process one page */
/* toss out extra counts and the back pointer */
for (k = 0; k < 10; k++) signed_quad();
for (op = get_byte(); op != EOP; op = get_byte()) {
/* interpret one command */
nxtcmd:
if (op >= SETC_000 && op <= SETC_127) {
putchar('(');
while (op <= 128) {
if (op == 128) {
p = get_byte();
printf("\\%c%c%c", p/0100 + '0',
((p/010) & 7) + '0', (p & 7)+'0');
} else if (op != '\\' && op != '(' && op != ')')
putchar(op);
else {
putchar('\\'); putchar(op);
}
op = get_byte();
switch (op) {
case W0:
putchar(' ');
op = get_byte();
break;
}
}
puts(")s");
goto nxtcmd;
} else if ((op >= FONT_00 && op <= FONT_63) ||
(op >= FNT1 && op <= FNT4)) {
p = first_par(op);
printf("f%d ", p);
} else {
p = first_par(op); /* get first parameter */
switch (op) {
case SET1: case SET2: case SET3: case SET4:
printf("(\\%c%c%c)s ", p/0100 + '0',
((p/010) & 7) + '0', (p & 7)+'0');
break;
case PUT1: case PUT2: case PUT3: case PUT4:
printf("(\\%c%c%c)p ", p/0100 + '0',
((p/010) & 7) + '0', (p & 7)+'0');
break;
case SET_RULE:
/* output rule and move, height in p */
width = signed_quad();
printf("%g %g rl\n", conv*(double)width,
conv*(double)p);
break;
case PUT_RULE:
/* output rule, height in p */
width = signed_quad();
printf("%g %g pr\n", conv*(double)width,
conv*(double)p);
break;
case NOP:
break;
case PUSH:
printf("S ");
break;
case POP:
printf("R ");
break;
case X0:
printf("x0 ");
break;
case X1: case X2: case X3: case X4:
printf("%g xs ", conv*(double)p);
break;
case W0:
printf("w0 ");
break;
case W1: case W2: case W3: case W4:
printf("%g ws ", conv*(double)p);
break;
case RIGHT1: case RIGHT2:
case RIGHT3: case RIGHT4:
printf("%g r ", conv*(double)p);
break;
case Z0:
printf("z0 ");
break;
case Z1: case Z2: case Z3: case Z4:
printf("%g zs ", conv*(double)p);
break;
case Y0:
printf("y0 "); break;
case Y1: case Y2: case Y3: case Y4:
printf("%g ys ", conv*(double)p); break;
case DOWN1: case DOWN2: case DOWN3: case DOWN4:
printf("%g d ", conv*(double)p);
break;
case FNT_DEF1: case FNT_DEF2:
case FNT_DEF3: case FNT_DEF4:
signed_quad();
scaled_size = signed_quad();
design_size = signed_quad();
waste = get_byte(); length = get_byte()+waste;
get_dvi_str(length, waste_string);
/* printf("/f%d { %g /%s tf } def\n", p,
((double)scaled_size)/
((double)design_size),
waste_string); */
break;
case XXX1: case XXX2: case XXX3: case XXX4:
get_dvi_str(p, waste_string);
do_special(waste_string);
break;
default:
error("Unknown or misplaced DVI command: %d",
op);
break;
}
}
}
puts("eop"); /* page separator */
pages_processed++;
break;
case FNT_DEF1: case FNT_DEF2: case FNT_DEF3: case FNT_DEF4:
p = first_par(op); /* skip external font no. */
signed_quad();
scaled_size = signed_quad();
design_size = signed_quad();
waste = get_byte(); length = get_byte()+waste;
get_dvi_str(length, waste_string);
/* printf("/f%d { %g /%s tf } def\n", p,
((double)scaled_size)/
((double)design_size),
waste_string); */
break;
}
}
puts("%%Trailer");
}
main(argc, argv)
int argc;
char **argv;
{
int i;
program_name = argv[0];
if (argc != 2) {
fprintf(stderr, "usage: %s dvi-file\n", argv[0]);
exit(-1);
}
printf("%%!PS-Adobe-1.0\n%%%%Title: %s\n", argv[1]);
open_dvi_file(argv[1]);
write_preamble_comment();
load_postamble_and_fonts();
find_starting_page();
process_pages();
}
error(s, a1, a2, a3, a4, a5, a6, a7, a8, a9)
char *s;
int a1, a2, a3, a4, a5, a6, a7, a8, a9;
{
fprintf(stderr, "%s: ", program_name);
fprintf(stderr, s, a1, a2, a3, a4, a5, a6, a7, a8, a9);
putc('\n', stderr);
exit(-1);
}
do_special(s)
char *s;
{
FILE *fp;
int c;
if (s[0] != '!') { puts(s); return; }
if (!strncmp(s, "!include", 8)) {
if (include_file(s+9)) {
fprintf(stderr, "%s: WARNING: cannot include file %s\n",
program_name, s+9);
return;
}
} else puts(s);
}